/***************************************************************
功能：驱动W2812B彩灯板
单片机类型：STC15系列单片机，本程序测试采用STC15F2K60S2
晶振：11.0592MHz，本程序测试采用内部晶振
控制管脚：P1.0 （可修改）
作者：电子设计与图形编程（微信公众号）
******************************************************************/

#include <STC15F2K60S2.h> // 根据你的STC15型号选择相应的头文件
#include <intrins.h> // 包含_nop_()函数

/****************************************************************
修改部分  WS2812B_PIN 连接单片机管脚
          LED_NUM 彩灯板的灯的数量   
*****************************************************************/ 
    #define WS2812B_PIN P10 // WS2812B的DIN连接到P1.0		
    #define LED_NUM 8



/****************************************************************
                    常用颜色定义   
*****************************************************************/ 
		#define GREEN 255,0,0  //绿色
		#define RED 0,255,0     //红色
		#define BLUE 0,0,255   //蓝色
		#define YELLOW 255,255,0 //黄色
		#define PURPLE 0,255,255 //紫色
		#define CYAN 255,0,255 //青色
		#define WHITE 255,255,255 //白色
		
    #define uint8_t unsigned char
		#define uint16_t unsigned int


/****************************************************************
               彩灯颜色设置缓存区   
*****************************************************************/ 

		uint8_t LED_COLOR[LED_NUM][4];
		
/****************************************************************
                      函数声明   
*****************************************************************/ 		
    void WS2812B_SendBit(uint8_t _bit);//发送位函数
    void WS2812B_SendByte(uint8_t byte);//发送字节函数
//    void WS2812B_SendPixel(uint8_t g, uint8_t r, uint8_t b);//发送像素函数
    void WS2812B_ResFrame(void);//驱动开始函数（重置）
		void WS2812B_Set_Color_Light(uint8_t n,uint8_t g, uint8_t r, uint8_t b,uint8_t l); //设置灯号，颜色，亮度函数
		void WS2812B_Send_All();//生效函数
		void WS2812B_delay_us(uint16_t us);//延时us函数
		

/****************************************************************
           延时函数，需要根据你的单片机时钟频率进行调整   
*****************************************************************/ 	
    void WS2812B_delay_us(uint16_t us) 
		{          
         while (us--) 
					{
                 _nop_(); // 插入nop指令作为简单的延时
			           _nop_();
						     _nop_();
						     _nop_();                  
          }
    }
		

		

/****************************************************************
           发送位函数 发送一个数据位  
*****************************************************************/ 	
    
    void WS2812B_SendBit(uint8_t bit_)
			{
				if (bit_) 
				{
					// 逻辑1：0.85us高电平，0.4us低电平
					WS2812B_PIN = 1;//逻辑1：0.85us高电平
					_nop_();_nop_();_nop_();	
					WS2812B_PIN = 0;//逻辑1：0.85us高电平
						_nop_();
				} 
				else 
				{
					// 逻辑0：0.4us高电平，0.85us低电平
					WS2812B_PIN = 1;
					_nop_();
					WS2812B_PIN = 0;
          _nop_();_nop_();_nop_();
				}
     }

		 
/****************************************************************
           发送字节函数   
*****************************************************************/ 
    void WS2812B_SendByte(uint8_t byte) 
		{
			uint8_t i=0;
			for ( i = 0; i < 8; i++)
			{
				WS2812B_SendBit(byte & 0x80); // 发送最高位
				byte <<= 1; // 左移一位准备发送下一位
      }
    }

/****************************************************************
           发送像素函数   
*****************************************************************/ 
    // 发送一个像素的GRB数据
//    void WS2812B_SendPixel(uint8_t g, uint8_t r, uint8_t b) 
//		{
//			WS2812B_SendByte(g); // 绿色
//			WS2812B_SendByte(r); // 红色
//			WS2812B_SendByte(b); // 蓝色
//    }


/****************************************************************
           起始帧函数   
*****************************************************************/ 
    // 开始一帧数据
    void WS2812B_ResFrame(void) 
		{
			WS2812B_PIN = 0; // 起始低电平至少50us
			WS2812B_delay_us(200);

    }


/****************************************************************
           彩灯设置生效函数   
*****************************************************************/		
		
		void WS2812B_Send_All() 
		{
			int i=0;
			unsigned int light=0;
			WS2812B_ResFrame();
			
			for(i=0;i<LED_NUM;i++)
			{
        light=LED_COLOR[i][3];
				WS2812B_SendByte(light*LED_COLOR[i][0]/100); // 绿色
			  WS2812B_SendByte(light*LED_COLOR[i][1]/100); // 红色
			  WS2812B_SendByte(light*LED_COLOR[i][2]/100); // 蓝色
			}
    }



/****************************************************************
           彩灯设置函数   
		n: 第几个灯（设置范围1-LED_NUM）
		g: 绿色值 （范围0-255）
		r: 红色值 （范围0-255）
		b: 蓝色值 （范围0-255）
		l: 亮度值 （范围0-100）
		
		例如：WS2812B_Set_Color_Light(2,0,60,80,20);  
		功能：设置第2颗灯的绿色值0，红色值60，蓝色值80，亮度20
		例如：WS2812B_Set_Color_Light(5,RED,50);  
		功能：设置第5颗灯为红色，亮度50
*****************************************************************/			
		void WS2812B_Set_Color_Light(uint8_t n,uint8_t g, uint8_t r, uint8_t b,uint8_t l) 
		{
			LED_COLOR[n-1][0]=g;
			LED_COLOR[n-1][1]=r;
			LED_COLOR[n-1][2]=b;
			LED_COLOR[n-1][3]=l;
    }
		




